package com.project.seckill.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.project.seckill.common.exception.MyException;
import com.project.seckill.entity.Order;
import com.project.seckill.entity.Product;
import com.project.seckill.entity.ProductStockLog;
import com.project.seckill.mapper.OrderMapper;
import com.project.seckill.service.OrderService;
import com.project.seckill.service.ProductService;
import com.project.seckill.service.ProductStockLogService;
import com.project.seckill.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.UUID;

@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Autowired
    private ProductService productService;

    @Autowired
    private ProductStockLogService productStockLogService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public void createOrderAsync(Integer userId, Long productId) {
        if (redisUtils.exists("product:stock:over:" + productId)) {
            log.info("已售罄");
            throw new MyException("已经售罄！");
        }
        //生成库存流水
        ProductStockLog productStockLog = productService.createProductStockLog(productId, 1);
        log.info("生成库存流水完成 [" + productStockLog.getId() + "]");

        //消息体
        JSONObject Object = new JSONObject();
        Object.put("productId",productId);
        Object.put("num",1);
        Object.put("productStockLogId",productStockLog.getId());

        //本地事务
        JSONObject objectMsg = new JSONObject();
        objectMsg.put("userId",userId);
        objectMsg.put("productId",productId);
        objectMsg.put("num",1);
        objectMsg.put("productStockLogId",productStockLog.getId());

        String topic = "seckill:create_stock";
        try {
            TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(topic, MessageBuilder.withPayload(Object.toString()).build(), objectMsg);
            if (sendResult.getLocalTransactionState() == LocalTransactionState.UNKNOW){
                throw new MyException("创建订单失败");
            }else if(sendResult.getLocalTransactionState() == LocalTransactionState.ROLLBACK_MESSAGE){
                throw new MyException("已售罄");
            }
        }catch (MessagingException e){
            throw new MyException("创建订单失败");
        }



    }

    @Override
    public Order createOrder(Integer userId, Long productId, Integer num, String productStockLogId) {
        Product product = productService.getById(productId);
        if (product == null) {
            throw new MyException("商品不存在");
        }
        //扣减库存
        boolean result = productService.decreaseStockInCache(productId);
        log.debug("预扣减库存完成 [" + result + "]");
        if (!result) {
            throw new MyException("已抢完");
        }
        //生成订单
        Order order = new Order();
        order.setOrderSn(UUID.randomUUID().toString().replace("-", ""));
        order.setCreateTime(new Date());
        order.setStatus("paying");
        order.setProductId(productId);
        order.setUserId(userId);
        this.save(order);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("productId", productId);
        jsonObject.put("num", 1);
        rocketMQTemplate.asyncSend("seckill:increate_sales", MessageBuilder.withPayload(jsonObject.toString()).build(), new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("扣减商品库存消息成功");
            }

            @Override
            public void onException(Throwable throwable) {
                log.error("扣减商品库存消息失败", throwable);
            }
        }, 60 * 1000);
        //更新订单流水状态
        productStockLogService.updateProductStockLogStatus(productStockLogId,1);
        return order;
    }
}
